import io
import math
import textwrap
import datetime
from threading import RLock


class TaskLogger:
    def __init__(self, output: io.FileIO = None):
        self._set_length(12)
        self._lock = RLock()
        self._output = output

    def _set_length(self, value):
        self.length = math.ceil(value / 4) * 4

    @property
    def indent(self):
        return self.length + 12

    def target(self, target):
        return TaskTargetLogger(self, target)

    def log(self, target: str, message: str = None, exit_code=None, sep='|'):
        with self._lock:
            if exit_code is not None:
                ok = "OK" if str(exit_code) == "0" else 'ERROR'
                message = f'{ok}, exit {exit_code}'
                sep = '*'
            self._set_length(max(len(target), self.length))
            message = str(message).rstrip()
            message = textwrap.indent(message, ' ' * self.indent)[self.indent:]
            t = datetime.datetime.now().strftime('%H:%M:%S')
            line = f'{t} {target:<{self.length}s} {sep} {message}\n'
            if self._output:
                self._output.write(line)
                self._output.flush()
            else:
                print(line, end='', flush=True)


class TaskTargetLogger:
    def __init__(self, logger, target):
        self.logger = logger
        self.target = target

    def log(self, *args, **kwargs):
        self.logger.log(self.target, *args, **kwargs)
